package com.yupi.springbootinit.statemachine.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 待办中心服务
 * 管理各部门的待办任务，支持任务创建、状态管理、批量处理
 */
@Slf4j
@Service
public class TaskCenterService {
    
    /**
     * 任务类型枚举
     */
    public enum TaskType {
        CREATE_PROCESS_SHEET("创建工艺单", "工程部"),
        CREATE_PRODUCTION_SCHEDULE("创建生产排期", "PMC"),
        PROCESS_EXECUTION("工序执行", "生产部"),
        QUALITY_INSPECTION("质量检验", "品质部"),
        REWORK("返工重做", "生产部");
        
        private final String description;
        private final String targetDepartment;
        
        TaskType(String description, String targetDepartment) {
            this.description = description;
            this.targetDepartment = targetDepartment;
        }
        
        public String getDescription() { return description; }
        public String getTargetDepartment() { return targetDepartment; }
    }
    
    /**
     * 任务状态枚举
     */
    public enum TaskStatus {
        PENDING("待处理"),
        IN_PROGRESS("处理中"),
        COMPLETED("已完成"),
        CANCELLED("已取消");
        
        private final String description;
        
        TaskStatus(String description) {
            this.description = description;
        }
        
        public String getDescription() { return description; }
    }
    
    /**
     * 待办任务实体
     */
    public static class Task {
        private Long taskId;
        private TaskType taskType;
        private Long businessId; // 关联的业务ID（订单ID或工序ID）
        private String department;
        private String title;
        private String description;
        private TaskStatus status;
        private LocalDateTime createTime;
        private LocalDateTime updateTime;
        private String assignee; // 分配给的具体用户
        private Integer priority; // 优先级 1-高 2-中 3-低
        
        // 构造函数
        public Task(TaskType taskType, Long businessId, String department, String title) {
            this.taskType = taskType;
            this.businessId = businessId;
            this.department = department;
            this.title = title;
            this.status = TaskStatus.PENDING;
            this.createTime = LocalDateTime.now();
            this.updateTime = LocalDateTime.now();
            this.priority = 2; // 默认中等优先级
        }
        
        // Getters and Setters
        public Long getTaskId() { return taskId; }
        public void setTaskId(Long taskId) { this.taskId = taskId; }
        
        public TaskType getTaskType() { return taskType; }
        public void setTaskType(TaskType taskType) { this.taskType = taskType; }
        
        public Long getBusinessId() { return businessId; }
        public void setBusinessId(Long businessId) { this.businessId = businessId; }
        
        public String getDepartment() { return department; }
        public void setDepartment(String department) { this.department = department; }
        
        public String getTitle() { return title; }
        public void setTitle(String title) { this.title = title; }
        
        public String getDescription() { return description; }
        public void setDescription(String description) { this.description = description; }
        
        public TaskStatus getStatus() { return status; }
        public void setStatus(TaskStatus status) { 
            this.status = status; 
            this.updateTime = LocalDateTime.now();
        }
        
        public LocalDateTime getCreateTime() { return createTime; }
        public LocalDateTime getUpdateTime() { return updateTime; }
        
        public String getAssignee() { return assignee; }
        public void setAssignee(String assignee) { this.assignee = assignee; }
        
        public Integer getPriority() { return priority; }
        public void setPriority(Integer priority) { this.priority = priority; }
    }
    
    // 内存存储任务（实际应用中应该使用数据库）
    private final Map<Long, Task> taskStorage = new ConcurrentHashMap<>();
    private Long taskIdCounter = 1L;
    
    /**
     * 创建待办任务
     */
    public Task createTask(TaskType taskType, Long businessId, String department, String title) {
        Task task = new Task(taskType, businessId, department, title);
        task.setTaskId(generateTaskId());
        
        // 根据任务类型设置描述和优先级
        switch (taskType) {
            case CREATE_PROCESS_SHEET:
                task.setDescription(String.format("订单 %s 需要创建工艺单", businessId));
                task.setPriority(1); // 高优先级
                break;
            case CREATE_PRODUCTION_SCHEDULE:
                task.setDescription(String.format("订单 %s 工艺已发布，需要创建生产排期", businessId));
                task.setPriority(1); // 高优先级
                break;
            case PROCESS_EXECUTION:
                task.setDescription(String.format("工序 %s 可以开始执行", businessId));
                task.setPriority(2); // 中等优先级
                break;
            case QUALITY_INSPECTION:
                task.setDescription(String.format("工序 %s 需要质量检验", businessId));
                task.setPriority(1); // 高优先级
                break;
            case REWORK:
                task.setDescription(String.format("工序 %s 检验不合格，需要返工", businessId));
                task.setPriority(1); // 高优先级
                break;
        }
        
        taskStorage.put(task.getTaskId(), task);
        
        log.info("创建待办任务: 任务ID={}, 类型={}, 部门={}, 业务ID={}", 
                task.getTaskId(), taskType, department, businessId);
        
        return task;
    }
    
    /**
     * 创建检验任务模板
     * 当工艺单发布时，预生成检验任务模板
     */
    public void createInspectionTemplates(Long orderId) {
        // 实际应用中应该根据工艺单中的检验要求生成检验任务模板
        // 这里简化处理
        log.info("为订单 {} 创建检验任务模板", orderId);
        
        // 模拟创建多个检验任务模板
        for (int i = 1; i <= 3; i++) {
            Task inspectionTemplate = createTask(
                TaskType.QUALITY_INSPECTION, 
                orderId * 100 + i, // 模拟工序ID
                "品质部", 
                String.format("工序%d检验", i)
            );
            inspectionTemplate.setStatus(TaskStatus.PENDING);
        }
    }
    
    /**
     * 创建首道工序任务
     */
    public void createFirstProcessTask(Long orderId) {
        // 实际应用中应该查询工艺单获取首道工序
        Long firstProcessId = orderId * 100 + 1; // 模拟首道工序ID
        
        Task firstProcessTask = createTask(
            TaskType.PROCESS_EXECUTION,
            firstProcessId,
            "生产部",
            "首道工序执行"
        );
        
        log.info("为订单 {} 创建首道工序任务: 工序ID={}", orderId, firstProcessId);
    }
    
    /**
     * 更新任务状态
     */
    public boolean updateTaskStatus(Long taskId, TaskStatus newStatus) {
        Task task = taskStorage.get(taskId);
        if (task != null) {
            TaskStatus oldStatus = task.getStatus();
            task.setStatus(newStatus);
            
            log.info("更新任务状态: 任务ID={}, 从 {} 到 {}", taskId, oldStatus, newStatus);
            return true;
        }
        
        log.warn("任务不存在: 任务ID={}", taskId);
        return false;
    }
    
    /**
     * 分配任务给用户
     */
    public boolean assignTask(Long taskId, String assignee) {
        Task task = taskStorage.get(taskId);
        if (task != null) {
            task.setAssignee(assignee);
            task.setStatus(TaskStatus.IN_PROGRESS);
            
            log.info("分配任务: 任务ID={}, 分配给={}", taskId, assignee);
            return true;
        }
        
        return false;
    }
    
    /**
     * 完成任务
     */
    public boolean completeTask(Long taskId, String completedBy) {
        Task task = taskStorage.get(taskId);
        if (task != null) {
            task.setStatus(TaskStatus.COMPLETED);
            if (task.getAssignee() == null) {
                task.setAssignee(completedBy);
            }
            
            log.info("完成任务: 任务ID={}, 完成人={}", taskId, completedBy);
            return true;
        }
        
        return false;
    }
    
    /**
     * 获取部门待办任务列表
     */
    public List<Task> getDepartmentTasks(String department, TaskStatus status) {
        return taskStorage.values().stream()
                .filter(task -> department.equals(task.getDepartment()))
                .filter(task -> status == null || status.equals(task.getStatus()))
                .sorted((t1, t2) -> {
                    // 按业务优先级排序：待处理 → 进行中 → 已完成
                    int statusCompare = getStatusPriority(t1.getStatus()) - getStatusPriority(t2.getStatus());
                    if (statusCompare != 0) {
                        return statusCompare;
                    }
                    // 状态相同时，按创建时间倒序排列（新的在前）
                    return t2.getCreateTime().compareTo(t1.getCreateTime());
                })
                .toList();
    }
    
    /**
     * 获取用户待办任务列表
     */
    public List<Task> getUserTasks(String assignee, TaskStatus status) {
        return taskStorage.values().stream()
                .filter(task -> assignee.equals(task.getAssignee()))
                .filter(task -> status == null || status.equals(task.getStatus()))
                .sorted((t1, t2) -> {
                    // 按业务优先级排序：待处理 → 进行中 → 已完成
                    int statusCompare = getStatusPriority(t1.getStatus()) - getStatusPriority(t2.getStatus());
                    if (statusCompare != 0) {
                        return statusCompare;
                    }
                    // 状态相同时，按创建时间倒序排列（新的在前）
                    return t2.getCreateTime().compareTo(t1.getCreateTime());
                })
                .toList();
    }
    
    /**
     * 批量处理任务
     */
    public int batchUpdateTaskStatus(List<Long> taskIds, TaskStatus newStatus) {
        int updatedCount = 0;
        for (Long taskId : taskIds) {
            if (updateTaskStatus(taskId, newStatus)) {
                updatedCount++;
            }
        }
        
        log.info("批量更新任务状态: 更新数量={}, 目标状态={}", updatedCount, newStatus);
        return updatedCount;
    }
    
    /**
     * 清理订单相关任务
     */
    public void cleanupOrderTasks(Long orderId) {
        List<Long> orderTaskIds = taskStorage.values().stream()
                .filter(task -> {
                    // 订单相关任务：订单ID匹配或工序ID以订单ID开头
                    return orderId.equals(task.getBusinessId()) || 
                           (task.getBusinessId() != null && 
                            task.getBusinessId().toString().startsWith(orderId.toString()));
                })
                .map(Task::getTaskId)
                .toList();
        
        // 将相关任务标记为已完成
        batchUpdateTaskStatus(orderTaskIds, TaskStatus.COMPLETED);
        
        log.info("清理订单相关任务: 订单ID={}, 清理任务数量={}", orderId, orderTaskIds.size());
    }
    
    /**
     * 获取任务统计信息
     */
    public Map<String, Object> getTaskStatistics(String department) {
        List<Task> departmentTasks = getDepartmentTasks(department, null);
        
        long pendingCount = departmentTasks.stream()
                .filter(task -> TaskStatus.PENDING.equals(task.getStatus()))
                .count();
        
        long inProgressCount = departmentTasks.stream()
                .filter(task -> TaskStatus.IN_PROGRESS.equals(task.getStatus()))
                .count();
        
        long completedCount = departmentTasks.stream()
                .filter(task -> TaskStatus.COMPLETED.equals(task.getStatus()))
                .count();
        
        Map<String, Object> statistics = new ConcurrentHashMap<>();
        statistics.put("department", department);
        statistics.put("totalTasks", departmentTasks.size());
        statistics.put("pendingTasks", pendingCount);
        statistics.put("inProgressTasks", inProgressCount);
        statistics.put("completedTasks", completedCount);
        
        return statistics;
    }
    
    /**
     * 生成任务ID
     */
    private synchronized Long generateTaskId() {
        return taskIdCounter++;
    }
    
    /**
     * 获取任务状态的优先级（用于排序）
     * @param status 任务状态
     * @return 优先级数字（越小优先级越高）
     */
    private int getStatusPriority(TaskStatus status) {
        if (status == null) {
            return Integer.MAX_VALUE;
        }
        switch (status) {
            case PENDING:
                return 1;     // 待处理优先级最高
            case IN_PROGRESS:
                return 2;     // 进行中次之
            case COMPLETED:
                return 3;     // 已完成最后显示
            case CANCELLED:
                return 4;     // 已取消最后显示
            default:
                return Integer.MAX_VALUE;
        }
    }
}